home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2008 February / PCWFEB08.iso / Software / Freeware / Miro 1.0 / Miro_Installer.exe / xulrunner / python / test / storedatabasetest.py < prev    next >
Encoding:
Python Source  |  2007-11-12  |  14.3 KB  |  416 lines

  1. from datetime import datetime
  2. import os
  3. import tempfile
  4. import unittest
  5.  
  6. import database
  7. import databaseupgrade
  8. import item
  9. import feed
  10. import schema
  11. import shutil
  12. import storedatabase
  13.  
  14. from test.framework import DemocracyTestCase
  15. # sooo much easier to type...
  16. from schema import SchemaString, SchemaInt, SchemaFloat, SchemaSimpleContainer
  17. from schema import SchemaList, SchemaDict, SchemaObject
  18.  
  19. # create a dummy schemma
  20. class Human:
  21.     def __init__(self, name, age, meters_tall, friends, high_scores = None):
  22.         self.name = name
  23.         self.age = age
  24.         self.meters_tall = meters_tall
  25.         self.friends = friends
  26.         if high_scores is None:
  27.             self.high_scores = {}
  28.         else:
  29.             self.high_scores = high_scores
  30.  
  31. class RestorableHuman(Human):
  32.     def onRestore(self):
  33.         self.iveBeenRestored = True
  34.  
  35. class Dog:
  36.     def __init__(self, name, age, owner=None):
  37.         self.name = name
  38.         self.age = age
  39.         self.owner = owner
  40.  
  41. class House:
  42.     def __init__(self, address, color, occupants, stuff=None):
  43.         self.address = address
  44.         self.color = color
  45.         self.occupants = occupants
  46.         self.stuff = stuff
  47.  
  48. class PCFProgramer(Human):
  49.     def __init__(self, name, age, meters_tall, friends, position, superpower,
  50.             high_scores = None):
  51.         Human.__init__(self, name, age, meters_tall, friends, high_scores)
  52.         self.position = position
  53.         self.superpower = superpower
  54.  
  55. class HumanSchema(schema.ObjectSchema):
  56.     klass = Human
  57.     classString = 'human'
  58.     fields = [
  59.         ('name', SchemaString()),
  60.         ('age', SchemaInt()),
  61.         ('meters_tall', SchemaFloat()),
  62.         ('friends', SchemaList(SchemaObject(Human))),
  63.         ('high_scores', SchemaDict(SchemaString(), SchemaInt())),
  64.     ]
  65.  
  66. class RestorableHumanSchema(HumanSchema):
  67.     klass = RestorableHuman
  68.     classString = 'restorable-human'
  69.  
  70. class DogSchema(schema.ObjectSchema):
  71.     klass = Dog
  72.     classString = 'dog'
  73.     fields = [
  74.         ('name', SchemaString()),
  75.         ('age', SchemaInt()),
  76.         ('owner', SchemaObject(Human, noneOk=True)),
  77.     ]
  78.  
  79. class HouseSchema(schema.ObjectSchema):
  80.     klass = House
  81.     classString = 'house'
  82.     fields = [
  83.         ('address', SchemaString()),
  84.         ('color', SchemaString()),
  85.         ('occupants', SchemaList(SchemaObject(Human))),
  86.         ('stuff', SchemaSimpleContainer(noneOk=True)),
  87.     ]
  88.  
  89. class PCFProgramerSchema(HumanSchema):
  90.     klass = PCFProgramer
  91.     classString = 'pcf-programmer'
  92.     fields = HumanSchema.fields + [
  93.         ('position', SchemaString()),
  94.         ('superpower', SchemaString()),
  95.     ]
  96.  
  97. testObjectSchemas = [HumanSchema, DogSchema, HouseSchema, PCFProgramerSchema,
  98.     RestorableHumanSchema]
  99.  
  100. class SchemaTest(DemocracyTestCase):
  101.     def setUp(self):
  102.         DemocracyTestCase.setUp(self)
  103.         storedatabase.skipUpgrade = True
  104.         self.lee = Human(u"lee", 25, 1.4, [], {u'virtual bowling': 212})
  105.         self.joe = Human(u"joe", 14, 1.4, [self.lee])
  106.         self.forbesSt = House(u'45 Forbs St', u'Blue', [self.lee, self.joe],
  107.                 {'view': u'pretty', 'next-party': datetime(2005, 4, 5)})
  108.         self.scruffy = Dog(u'Scruffy', 3, self.lee)
  109.         self.spike = Dog(u'Spike', 4, owner=None)
  110.         self.db = [ self.lee, self.joe, self.forbesSt, self.scruffy, 
  111.             self.spike]
  112.         self.savePath = tempfile.mktemp()
  113.  
  114.     def tearDown(self):
  115.         storedatabase.skipUpgrade = False
  116.         try:
  117.             os.unlink(self.savePath)
  118.         except OSError:
  119.             pass
  120.         DemocracyTestCase.tearDown(self)
  121.  
  122.     def addSubclassObjects(self):
  123.         self.ben = PCFProgramer(u'ben', 25, 3.4, [], u'programmer',
  124.                 u'Teleportation')
  125.         self.holmes = PCFProgramer(u'ben', 25, 3.4, [], u'co-director', 
  126.                 u'Mind Control')
  127.         self.forbesSt.occupants.extend([self.ben, self.holmes])
  128.         self.db.extend([self.ben, self.holmes])
  129.  
  130. class TestValidation(SchemaTest):
  131.     def assertDbValid(self):
  132.         storedatabase.objectsToSavables(self.db, testObjectSchemas)
  133.  
  134.     def assertDbInvalid(self):
  135.         self.assertRaises(schema.ValidationError,
  136.                 storedatabase.objectsToSavables, self.db, testObjectSchemas)
  137.  
  138.     def tesntValidDb(self):
  139.         self.assertDbValid()
  140.  
  141.     def testNoneValues(self):
  142.         self.lee.age = None
  143.         self.assertDbInvalid()
  144.         self.lee.age = 25
  145.         self.scruffy.owner = None
  146.         self.assertDbValid()
  147.  
  148.     def testIntValidation(self):
  149.         self.lee.age = '25'
  150.         self.assertDbInvalid()
  151.         self.lee.age = 25L
  152.         self.assertDbValid()
  153.  
  154.     def testStringValidation(self):
  155.         self.lee.name = 133
  156.         self.assertDbInvalid()
  157.         self.lee.name = u'lee'
  158.         self.assertDbValid()
  159.  
  160.     def testFloatValidation(self):
  161.         self.lee.meters_tall = 3
  162.         self.assertDbInvalid()
  163.  
  164.     def testListValidation(self):
  165.         self.lee.friends = [u'joe']
  166.         self.assertDbInvalid()
  167.  
  168.     def testDictValidation(self):
  169.         self.joe.high_scores['pong'] = u"One Million"
  170.         self.assertDbInvalid()
  171.         del self.joe.high_scores['pong']
  172.         self.joe.high_scores[1943] = 1234123
  173.         self.assertDbInvalid()
  174.  
  175.     def testSubclassValidation(self):
  176.         self.addSubclassObjects()
  177.         self.assertDbValid()
  178.         class HumanSubclassWithoutObjectSchema(Human):
  179.             pass
  180.         jimmy = HumanSubclassWithoutObjectSchema(u"Luc", 23, 3.4, [])
  181.         self.joe.friends.append(jimmy)
  182.         self.assertDbInvalid()
  183.  
  184. class TestSave(SchemaTest):
  185.     def testSimpleCircularReference(self):
  186.         self.lee.friends = [self.joe]
  187.  
  188.     def testSaveToDisk(self):
  189.         storedatabase.saveObjectList(self.db, self.savePath,
  190.                 testObjectSchemas)
  191.  
  192.     def testExtraObjectsAreIgnored(self):
  193.         class EpherialObject:
  194.             pass
  195.         self.db.append(EpherialObject())
  196.         storedatabase.objectsToSavables(self.db, testObjectSchemas)
  197.  
  198. class TestRestore(SchemaTest):
  199.     def testSaveThenRestore(self):
  200.         storedatabase.saveObjectList(self.db, self.savePath,
  201.                 testObjectSchemas)
  202.         db2 = storedatabase.restoreObjectList(self.savePath,
  203.                 testObjectSchemas)
  204.         # check out the humans
  205.         lee2, joe2, forbesSt2, scruffy2, spike2 = db2
  206.         for attr in 'name', 'age', 'meters_tall', 'high_scores':
  207.             self.assertEquals(getattr(self.lee, attr), getattr(lee2, attr))
  208.             self.assertEquals(getattr(self.joe, attr), getattr(joe2, attr))
  209.         self.assertEquals(joe2.friends, [lee2])
  210.         # check out the house
  211.         self.assertEquals(forbesSt2.address, u'45 Forbs St')
  212.         self.assertEquals(forbesSt2.color, u'Blue')
  213.         self.assertEquals(forbesSt2.occupants, [lee2, joe2])
  214.         self.assertEquals(forbesSt2.stuff,
  215.                 {'view': u'pretty', 'next-party': datetime(2005, 4, 5)})
  216.         # check out the dogs
  217.         self.assertEquals(scruffy2.name, u'Scruffy')
  218.         self.assertEquals(scruffy2.age, 3)
  219.         self.assertEquals(spike2.name, u'Spike')
  220.         self.assertEquals(spike2.age, 4)
  221.         self.assertEquals(scruffy2.owner, lee2)
  222.         self.assertEquals(spike2.owner, None)
  223.  
  224.     def testRestoreSubclasses(self):
  225.         self.addSubclassObjects()
  226.         storedatabase.saveObjectList(self.db, self.savePath, testObjectSchemas)
  227.         db2 = storedatabase.restoreObjectList(self.savePath, testObjectSchemas)
  228.         lee2, joe2, forbesSt2, scruffy2, spike2, ben2, holmes2 = db2
  229.         for attr in ('name', 'age', 'meters_tall', 'high_scores', 'position',
  230.                 'superpower'):
  231.             self.assertEquals(getattr(self.ben, attr), getattr(ben2, attr))
  232.             self.assertEquals(getattr(self.holmes, attr), getattr(holmes2,
  233.                 attr))
  234.         self.assertEquals(forbesSt2.occupants, [lee2, joe2, ben2, holmes2])
  235.  
  236.     def testOnRestoreCalled(self):
  237.         resto = RestorableHuman(u'resto', 23, 1.3, [])
  238.         self.db.append(resto)
  239.         storedatabase.saveObjectList(self.db, self.savePath, testObjectSchemas)
  240.         db2 = storedatabase.restoreObjectList(self.savePath, testObjectSchemas)
  241.         lee2, joe2, forbesSt2, scruffy2, spike2, resto2, = db2
  242.         self.assertEquals(resto2.name, u'resto')
  243.         self.assert_(hasattr(resto2, 'iveBeenRestored'))
  244.         self.assertEquals(resto2.iveBeenRestored, True)
  245.  
  246. class UpgradeTest(SchemaTest):
  247.     def setUp(self):
  248.         super(UpgradeTest, self).setUp()
  249.         # save the actual version and upgrade functions
  250.         self.realSchemaVersion = schema.VERSION
  251.         try:
  252.             self.realUpgrade2 = databaseupgrade.upgrade2
  253.         except AttributeError:
  254.             self.realUpgrade2 = None
  255.         try:
  256.             self.realUpgrade3 = databaseupgrade.upgrade3
  257.         except AttributeError:
  258.             self.realUpgrade3 = None
  259.         # save the database, this is our "old" version
  260.         schema.VERSION = 1
  261.         storedatabase.saveObjectList(self.db, self.savePath,
  262.                 testObjectSchemas)
  263.         # install a fake upgrade path
  264.         schema.VERSION = 3
  265.         def upgrade2(objects):
  266.             for o in objects:
  267.                 if o.classString == 'human':
  268.                     o.savedData['name'] = "Sir %s" % o.savedData['name']
  269.         def upgrade3(objects):
  270.             for o in objects:
  271.                 if o.classString == 'dog':
  272.                     o.savedData['color'] = u"Unknown"
  273.         databaseupgrade.upgrade2 = upgrade2
  274.         databaseupgrade.upgrade3 = upgrade3
  275.         storedatabase.skipUpgrade = False
  276.         class DogSchema2(schema.ObjectSchema):
  277.             klass = Dog
  278.             classString = 'dog'
  279.             fields = [
  280.                 ('name', SchemaString()),
  281.                 ('age', SchemaInt()),
  282.                 ('owner', SchemaObject(Human, noneOk=True)),
  283.                 ('color', SchemaString()),
  284.             ]
  285.         self.nextGenObjectSchemas = [ HumanSchema, DogSchema2, HouseSchema,
  286.             PCFProgramerSchema, RestorableHumanSchema ]
  287.  
  288.     def tearDown(self):
  289.         if self.realUpgrade3 is not None:
  290.             databaseupgrade.upgrade3 = self.realUpgrade3
  291.         else:
  292.             del databaseupgrade.upgrade3
  293.         if self.realUpgrade2 is not None:
  294.             databaseupgrade.upgrade2 = self.realUpgrade2
  295.         else:
  296.             del databaseupgrade.upgrade2
  297.         schema.VERSION = self.realSchemaVersion
  298.         super(UpgradeTest, self).tearDown()
  299.  
  300.     def testChanges(self):
  301.         newDb = storedatabase.restoreObjectList(self.savePath,
  302.                 self.nextGenObjectSchemas)
  303.         for object in newDb:
  304.             if isinstance(object, Human):
  305.                 self.assert_(object.name.startswith("Sir "))
  306.             elif isinstance(object, Dog):
  307.                 self.assert_('color' in object.__dict__)
  308.  
  309.     def testRestoreWithNewerVersion(self):
  310.         newDb = storedatabase.restoreObjectList(self.savePath,
  311.                 self.nextGenObjectSchemas)
  312.         storedatabase.saveObjectList(newDb, self.savePath,
  313.                 testObjectSchemas)
  314.         # saved database is now version 3
  315.         schema.VERSION = 1
  316.         self.assertRaises(databaseupgrade.DatabaseTooNewError,
  317.                 storedatabase.restoreObjectList, self.savePath, 
  318.                 testObjectSchemas)
  319.  
  320.     def testSavingUpgradedDb(self):
  321.         newDb = storedatabase.restoreObjectList(self.savePath,
  322.                 self.nextGenObjectSchemas)
  323.         storedatabase.saveObjectList(newDb, self.savePath,
  324.                 self.nextGenObjectSchemas)
  325.         newDb = storedatabase.restoreObjectList(self.savePath,
  326.                 self.nextGenObjectSchemas)
  327.  
  328. class LiveStorageTest(DemocracyTestCase):
  329.     def setUp(self):
  330.         DemocracyTestCase.setUp(self)
  331.         storedatabase.skipUpgrade = True
  332.         self.savePath = os.path.join(tempfile.gettempdir(),
  333.                 'democracy-temp-db')
  334.         self.database = database.defaultDatabase
  335.         self.database.liveStorage = storedatabase.LiveStorage(self.savePath,
  336.                 restore=False)
  337.  
  338.     def tearDown(self):
  339.         storedatabase.skipUpgrade = False
  340.         try:
  341.             self.database.liveStorage.close()
  342.             self.database.liveStorage = None
  343.         except:
  344.             pass
  345.         try:
  346.             shutil.rmtree(self.savePath);
  347.         except:
  348.             pass
  349.         DemocracyTestCase.tearDown(self)
  350.  
  351.  
  352. class TestConstraintChecking(LiveStorageTest):
  353.     def testConstraintCheck(self):
  354.         # test creating an item with an invalid feed id
  355.         self.assertRaises(database.DatabaseConstraintError,
  356.                 item.Item, 123123123, {})
  357.  
  358.     def testConstraintCheck2(self):
  359.         # test changing an item to have an invalid feed id
  360.         f = feed.Feed(u"http://feed.uk")
  361.         i = item.Item({}, feed_id=f.id)
  362.         i.feed_id = 123456789
  363.         self.assertRaises(database.DatabaseConstraintError, i.signalChange)
  364.  
  365.     def testUpdateAfterRemove(self):
  366.         obj = database.DDBObject()
  367.         obj.remove()
  368.         self.assertRaises(database.DatabaseConstraintError, obj.signalChange)
  369.  
  370. class TestHighLevelFunctions(LiveStorageTest):
  371.     def setUp(self):
  372.         LiveStorageTest.setUp(self)
  373.         self.f = feed.Feed(u"http://feed.uk")
  374.         i = item.Item({}, feed_id=self.f.id)
  375.         i2 = item.Item({}, feed_id=self.f.id)
  376.         self.objects = [self.f, i, i2]
  377.  
  378.     def checkDatabaseIsTheSame(self):
  379.         self.assertEquals(len(self.objects), len(self.database.objects))
  380.  
  381.         # We can't directly compare objects, since that would compare their
  382.         # ids.  As a sanity test, compare that we have the same classes coming
  383.         # out and we did going in.
  384.         i = 0
  385.         for newObject, copy in self.database.objects:
  386.             self.assertEquals(type(newObject), type(self.objects[i]))
  387.             self.assertEquals(newObject.id, self.objects[i].id)
  388.             i += 1
  389.  
  390.     def saveDatabase(self):
  391.         self.database.liveStorage.saveDatabase()
  392.  
  393.     def restoreDatabase(self):
  394.         database.resetDefaultDatabase()
  395.         self.database.liveStorage = storedatabase.LiveStorage(self.savePath,
  396.                 restore=True)
  397.  
  398.     def testSaveThenRestore(self):
  399.         self.saveDatabase()
  400.         self.restoreDatabase()
  401.         self.checkDatabaseIsTheSame()
  402.  
  403.     def testUpdateThenRestore(self):
  404.         i3 = item.Item({}, feed_id=self.f.id)
  405.         self.saveDatabase()
  406.         i3.remove()
  407.         i3 = item.Item({}, feed_id=self.f.id)
  408.         self.objects.append(i3)
  409.         self.database.liveStorage.runUpdate()
  410.         self.restoreDatabase()
  411.         self.checkDatabaseIsTheSame()
  412.  
  413.  
  414. if __name__ == '__main__':
  415.     unittest.main()
  416.